<?php
namespace api\modules\v1\models\user;

use api\modules\v1\models\Common;
use api\modules\v1\models\prop\PropUserWarehouse;
use api\modules\v1\models\userReceipt\Receipt;
use common\models\CacheKeys;
use common\models\config\ConfigAddress;
use common\models\Functions;
use common\models\im\Im;
use common\models\Patterns;
use common\models\Sign;
use common\models\Status;
use common\models\user\UserLoginStatistic;
use common\services\position\PositionAliyun;
use Yii;
use yii\base\Exception;
use yii\helpers\StringHelper;

class UserAccount extends \api\modules\common\models\User
{

    public $password;
    public $re_password;
    public $re_pay_password;
    public $code;
    public $user;

    /**
     * 验证规则
     */
    public function rules()
    {
        return [
            # 注册
            [['login_name', 'password', 'code', 'invite_code','re_password'], 'required', 'message' => '{attribute}不能为空', 'on' => 'register'],
            [['login_name', 'password'], 'filter', 'filter' => 'trim', 'on' => ['register']],
            ['re_password', 'compare', 'compareAttribute' => 'password', 'message' => '密码不一致', 'on' => 'register'],
            ['password', 'string', 'min' => 5, 'max' => 18, 'message' => '新密码长度必须为5~18', 'on' => 'register'],
            ['login_name', 'validateRegisterName', 'on' => 'register'],
            ['code', 'validateCheckPhoneCode', 'on' => 'register'],

            # 账号密码登录
            [['login_name', 'password'], 'required', 'message' => '{attribute}不能为空', 'on' => 'loginByPass'],
            [['login_name', 'password'], 'filter', 'filter' => 'trim', 'on' => ['loginByPass']],
            [['login_name'], 'match', 'pattern' => Patterns::phoneNumber(), 'message' => '手机号码格式不正确', 'on' => ['loginByPass', "register"]],
            ['login_name', 'validateLoginName', 'on' => 'loginByPass'],
            ['password', 'validatePassword', 'on' => 'loginByPass'],

            # 验证码登录
            [['code', 'login_name'], 'required', 'message' => '{attribute}不能为空', 'on' => 'loginByCode'],
            ['login_name', 'validateLoginName', 'on' => 'loginByCode'],
            ['code', 'validateCheckPhoneCode', 'on' => 'loginByCode'],

            # 忘记密码
            [['login_name', 'code', 'password','re_password'], 'required', 'message' => '{attribute}不能为空', 'on' => 'forgetPassword'],
            [['login_name'], 'match', 'pattern' => Patterns::phoneNumber(), 'message' => '手机号码格式不正确', 'on' => ['forgetPassword']],
            [['login_name', 'code', 'password', 're_password'], 'filter', 'filter' => 'trim', 'on' => ['forgetPassword']],
            ['password', 'string', 'min' => 5, 'max' => 18, 'message' => '新密码长度必须为5~18', 'on' => 'forgetPassword'],
            ['re_password', 'compare', 'compareAttribute' => 'password', 'message' => '密码不一致', 'on' => 'forgetPassword'],
            ['login_name', 'validateForgetPhone', 'on' => 'forgetPassword'],
            ['code', 'validateCheckPhoneCode', 'on' => 'forgetPassword'],

            # 修改新密码
            [['code', 'password', 're_password'], 'required', 'message' => '{attribute}不能为空', 'on' => 'modifyPassword'],
            ['re_password', 'compare', 'compareAttribute' => 'password', 'message' => '密码不一致', 'on' => 'modifyPassword'],
            ['password', 'string', 'min' => 5, 'max' => 18, 'message' => '新密码长度必须为5~18', 'on' => 'modifyPassword'],
            ['code', 'validateCheckPhoneCode', 'on' => 'modifyPassword'],

            # 设置修改支付密码
            [['code', 'pay_password', 're_pay_password'], 'required', 'message' => '{attribute}不能为空', 'on' => 'payPassword'],
            ['re_pay_password', 'compare', 'compareAttribute' => 'pay_password', 'message' => '密码不一致', 'on' => 'payPassword'],
//            ['pay_password', 'string', 'min' => 6, 'max' => 6, 'message' => '支付密码长度必须为6位', 'on' => 'payPassword'],
            ['code', 'validateCheckPhoneCode', 'on' => 'payPassword'],


            # 修改钱包开关
            [['code', 'money_switch'], 'required', 'message' => '{attribute}不能为空', 'on' => 'moneySwitch'],
            ['code', 'validateCheckPhoneCode', 'on' => 'moneySwitch'],
        ];
    }

    /**
     * 设置属性名称
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'login_name' => '账号',
            'nick_name' => '账号',
            'password' => '密码',
            're_password' => '确认密码',
            'phone' => '手机号',
            'status' => '状态',
            'code' => '验证码',
            'pay_password' => '支付密码',
            're_pay_password' => '确认支付密码',
            'money_switch' => '钱包开关',
        ];
    }

    /**
     * 设置场景
     * @return array
     */
    public function scenarios()
    {
        $newScenarios = [
            'loginByPass' => [
                'login_name', 'password',
            ],

            'register' => [
                'login_name', 'code', 'password', 're_password',
            ],

            'forgetPassword' => [
                'login_name', 'code', 'password', 're_password',
            ],

            'modifyPassword' => [
                'password', 're_password', 'code',
            ],

            'loginByCode' => [
                'login_name', 'code',
            ],

            'payPassword' => [
                'pay_password', 're_pay_password', 'code',
            ],

            'moneySwitch' => [
                'money_switch', 'code',
            ],
        ];
        return array_merge(parent::scenarios(), $newScenarios);
    }


    // 验证登录
    public function validateLoginName($attribute)
    {
        if (!$this->hasErrors()) {
            $where['login_name'] = $this->login_name;
            $this->user = !$this->user ? static::getOneByWhere($where) : $this->user;
            if (!empty($this->user)) {
                if ($this->user['status'] == Status::COMMON_STATUS_HIDDEN) {
                    throw new Exception('账号被冻结，请联系客服');
                }
            } else {
                $this->addError($attribute, '账号不存在.');
            }
        }
    }

    // 验证登录密码
    public function validatePassword($attribute)
    {
        if (!$this->hasErrors()) {
            $this->user = !$this->user ? static::getOneByWhere($where) : $this->user;
            if (!empty($this->user)) {
                if ((!Yii::$app->security->validatePassword($this->password, $this->user['password_hash']))) {
                    $this->addError($attribute, '密码错误.');
                }
            } else {
                $this->addError($attribute, '账号不存在.');
            }
        }
    }


    // 验证注册手机号
    public function validateRegisterName($attribute)
    {
        if (!$this->hasErrors()) {
            $andWhere[] = ['OR', ['login_name' => $this->login_name]];
            $this->user = static::getByAndWhere([], $andWhere);
            if (!empty($this->user)) {
                $this->addError($attribute, '该手机号已被注册.');
            }
        }
    }

    // 验证忘记密码手机号
    public function validateForgetPhone($attribute)
    {
        if (!$this->hasErrors()) {
            $andWhere[] = ['OR', ['login_name' => $this->login_name], ['phone' => $this->login_name]];
            $this->user = static::getByAndWhere([], $andWhere);
            if (empty($this->user)) {
                $this->addError($attribute, '未发现该账号信息.');
            }
        }
    }

    // 验证验证码
    public function validateCheckPhoneCode($attribute)
    {
        if (!$this->hasErrors()) {
            $currentScenario = $this->scenario;
            switch ($currentScenario) {
                case 'register':
                    Common::checkPhoneCode($this->login_name, $this->code, CacheKeys::CACHE_CODE_TYPE_REGISTER_CODE);
                    break;
                case 'forgetPassword':
                    Common::checkPhoneCode($this->login_name, $this->code, CacheKeys::CACHE_CODE_TYPE_FORGET_CODE);
                    break;
                case 'modifyPassword':
                    $this->user = Yii::$app->getUser()->getIdentity();
                    Common::checkPhoneCode($this->user->phone, $this->code, CacheKeys::CACHE_CODE_TYPE_MODIFY_PASSWORD_PHONE);
                    break;
                case 'loginByCode':
                    if ($this->user['is_login_by_code'] == Status::COMMON_RADIO_NO) {
                        $this->addError($attribute, '您已关闭验证码登录！');
                    }
                    Common::checkPhoneCode($this->login_name, $this->code, CacheKeys::CACHE_CODE_TYPE_LOGIN);
                    break;
                case 'payPassword':
                    $this->user = Yii::$app->getUser()->getIdentity();
                    Common::checkPhoneCode($this->user->phone, $this->code, CacheKeys::CACHE_CODE_TYPE_RESET_PAY_PASS_CODE);
                    break;

                case 'moneySwitch':
                    $this->user = Yii::$app->getUser()->getIdentity();
                    Common::checkPhoneCode($this->user->phone, $this->code, CacheKeys::CACHE_CODE_TYPE_MONEY_SWITCH_CODE);
                    break;
            }
        }
    }


    /**
     * 用户注册
     * @return array
     */
    public function userRegister()
    {
        $trans = Yii::$app->db->beginTransaction();
        $key = "REGISTER_" . $this->login_name;
        try {

            $config = static::getCommonByKey('close_register');
            if ($config == Status::COMMON_RADIO_NO) {
                throw new Exception('系统维护，暂停注册！');
            }

            $exists = Yii::$app->redis->get($key);
            if($exists){
                throw new Exception('正在注册中！');
            }
            Yii::$app->redis->set($key, true);

            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }

//            CacheKeys::checkFrequency();

            $data['login_name'] = $this->login_name;
            $data['nick_name'] = $this->_createNickname();
            $data['phone'] = $this->login_name;
            $data['parent_id'] = 0;
            $data['parent_path'] = "0,";
            $data['invite_code'] = $this->_createInviteCode();

            # 检查密码规则
            Functions::checkLoginPassword($this->password);
            $data['password_hash'] = Yii::$app->security->generatePasswordHash($this->password);
            $data['register_time'] = date("Y-m-d H:i:s");

            # 位置
            list($longitude,$latitude) = $this->getPosition($this->login_name);
            $data['longitude'] = $longitude;
            $data['latitude'] = $latitude;
            $res = static::insertData($data);
            if ($res === false) {
                throw new Exception('注册失败');
            }

            $data['id'] = $res;
            //注册IM
            $imUser = $this->createImUser($data);

            // 添加客服账号
            // 添加客服
            $this->addServerUserFriend($imUser['id']);
            $trans->commit();
            return Functions::formatRestAPI(0, '注册成功，快去登录吧！');
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '数据异常');
        } catch (Exception $e) {
            $trans->rollBack();
            return Functions::formatRestAPI(1, $e->getMessage());
        } finally {
            Yii::$app->redis->del($key);
        }
    }

    /**
     * 账号密码登录
     * @return array
     */
    public function doLoginByPass()
    {
        $trans = Yii::$app->db->beginTransaction();
        $post = Yii::$app->request->post();
        $key = "LOGIN_" . $this->login_name;
        try {
            $exists = Yii::$app->redis->get($key);
            if($exists){
                throw new Exception('正在登录中！');
            }
            Yii::$app->redis->set($key, true);

//            UserLoginErrorLog::chkTodayError(3, 8, 15);

            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }

            // 检查设备码
            Common::checkDeviceCode($this->user);

            $data = $this->_login($this->login_name);


            $trans->commit();

            return Functions::formatRestAPI(0, '登录成功', $data);
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '数据异常');
        } catch (Exception $e) {
            $trans->rollBack();
            if ($e->getCode() != 2000) {
                UserLoginErrorLog::recordLog($post['login_name'], $post['password'], $e->getMessage());
            }
            return Functions::formatRestAPI($e->getCode() ? $e->getCode() : 1, $e->getMessage());
        } finally {
            Yii::$app->redis->del($key);
        }
    }

    /**
     * 验证码登录
     * @return array
     */
    public function doLoginByCode()
    {
        $trans = Yii::$app->db->beginTransaction();
        $post = Yii::$app->request->post();
        $loginName = $post['login_name'];
        $code = $post['code'];
        $key = "LOGIN_" . $loginName;
        try {
            $exists = Yii::$app->redis->get($key);
            if($exists){
                throw new Exception('正在登录中！');
            }
            Yii::$app->redis->set($key, true);
            UserLoginErrorLog::chkTodayError(3, 8, 15);

            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }
//            (new Sign())->checkParams();


            $data = $this->_login($loginName);

            $trans->commit();

            return Functions::formatRestAPI(0, '登录成功', $data);
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '数据异常');
        } catch (Exception $e) {
            $trans->rollBack();
            if ($e->getCode() == 2000) {
                UserLoginErrorLog::recordLog($loginName, $code, $e->getMessage());
            }
            return Functions::formatRestAPI(1, $e->getMessage());
        } finally {
            Yii::$app->redis->del($key);
        }
    }

    //执行登录操作
    public function _login($loginName = '') {
        $versionCode = strtolower(Yii::$app->request->headers->get('version-code', ''));
        $this->access_token = $this->user['access_token'];
        $this->refresh_token = '';

        if (!$this->authKeyIsValid($this->access_token)) {
            $this->generateAuthKey();
        }

        //更新登录态
        $data['access_token'] = $update['access_token'] = $this->access_token;
        $data['refresh_token'] = $update['refresh_token'] = $this->refresh_token;
        $data['login_name'] = $loginName;
        $update['versions'] = $versionCode;
        $update['update_time'] = date('Y-m-d H:i:s');

        $where['login_name'] = $loginName;
        $res = static::updateData($update, $where);
        if ($res === false) {
            throw new Exception('登录失败');
        }

        // 判断最后登录时间
        $lastLoginInfo = UserLoginLog::getOneByWhere(['user_id' => $this->user['id']],['login_time'],'id DESC');
        $data['need_setting'] = false;
        $data['need_greet'] = false;
        if (empty($lastLoginInfo)) {
            $data['need_setting'] = true;
            $data['need_greet'] = true;
        } else {
            if ($this->user['is_setting'] == Status::COMMON_RADIO_NO) {
                $data['need_setting'] = true;
            }

            if (date('Y-m-d H:i:s',strtotime('-7 days')) > $lastLoginInfo['login_time']) {
                $data['need_greet'] = true;
            }
        }




        UserLoginLog::recordLog($this->user['id']);
        UserLoginStatistic::record($loginName);
        return $data;
    }

    // 退出登录
    public function logout()
    {
        try {
            $user = static::checkUser();

            $data['access_token'] = '';
            $data['update_time'] = date("Y-m-d H:i:s");

            static::updateData($data, ['id' => $user['id']]);

            return Functions::formatRestAPI(0, '退出成功');
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, '退出失败');
        }
    }

    /**
     * 忘记密码
     * @return array
     */
    public function forgetPasswordForLogin()
    {
        $key = "FORGET_" . $this->login_name;
        try {
            $exists = Yii::$app->redis->get($key);
            if($exists){
                throw new Exception('操作频繁！');
            }
            Yii::$app->redis->set($key, true);
            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }
            # 检查密码规则
            Functions::checkLoginPassword($this->password);
            $data['password_hash'] = Yii::$app->security->generatePasswordHash($this->password);
            $data['update_time'] = date("Y-m-d H:i:s");
            $res = static::updateData($data, ['login_name' => $this->login_name]);

            if ($res === false) {
                throw new Exception('系统错误，请稍后再试');
            }

            return Functions::formatRestAPI(0, '修改成功，请牢记密码');
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '数据异常');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }  finally {
            Yii::$app->redis->del($key);
        }
    }

    /**
     * 修改密码
     * @return array
     */
    public function modifyPassword()
    {
        try {
            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }
            # 检查密码规则
            Functions::checkLoginPassword($this->password);
            $data['password_hash'] = Yii::$app->security->generatePasswordHash($this->password);
            $data['update_time'] = date("Y-m-d H:i:s");
            $res = static::updateData($data, ['id' => $this->user['id']]);

            if ($res === false) {
                throw new Exception('系统错误，请稍后再试');
            }

            # APP踢下线
            (new Im()) ->loginOut($this->user['tx_code']);

            return Functions::formatRestAPI(0, '修改成功，请牢记密码');
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    /**
     * 设置修改支付密码
     * @return array
     */
    public function modifyPayPassword()
    {
        try {
            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }

            # 检查密码规则
            Functions::checkNumberPassword($this->pay_password);
            $data['pay_password'] = Yii::$app->security->generatePasswordHash($this->pay_password);
            $data['update_time'] = date("Y-m-d H:i:s");
            $res = static::updateData($data, ['id' => $this->user['id']]);

            if ($res === false) {
                throw new Exception('系统错误，请稍后再试');
            }
            return Functions::formatRestAPI(0, '设置成功');
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    /**
     * 修改钱包开关
     * @return array
     */
    public function moneySwitch()
    {
        try {

            if (!$this->validate()) {
                throw new Exception($this->getErrorSummary(true)[0]);
            }
            if (!in_array($this->money_switch,[Status::COMMON_RADIO_YES,Status::COMMON_RADIO_NO])) {
                throw new Exception('参数错误！');
            }

            # 检查密码规则
            $data['money_switch'] = $this->money_switch;
            $data['update_time'] = date("Y-m-d H:i:s");
            $res = static::updateData($data, ['id' => $this->user->id]);

            if ($res === false) {
                throw new Exception('系统错误，请稍后再试');
            }
            return Functions::formatRestAPI(0, '设置成功');
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

}
